﻿#ifndef SHAPEBASEDMATCH_H
#define SHAPEBASEDMATCH_H

#include "line2Dup.h"

namespace Qly
{

void test01();
void test02();
inline void drawRotatedRect(cv::Mat &image, const cv::RotatedRect &rr, cv::Scalar color, int thickness = 1)
{
    cv::Point2f pts[4];
    rr.points(pts);
    cv::line(image, pts[0], pts[1], color, thickness);
    cv::line(image, pts[1], pts[2], color, thickness);
    cv::line(image, pts[2], pts[3], color, thickness);
    cv::line(image, pts[0], pts[3], color, thickness);
}

/**
 * @brief The ShapeBasedMatching class 这个类作为其他类的基类，提供一些基础的功能
 */
class ShapeBasedMatching
{
public:
    struct MatchResult
    {
        cv::RotatedRect rect;
        float scale;
        float score;
        int template_id;
    };

    ShapeBasedMatching();
    virtual bool saveModel(std::string path, std::string modelName) = 0;
    virtual bool loadModel(std::string path, std::string modelName) = 0;
    virtual std::vector<MatchResult> runMatch(const cv::Mat &testImg, float score, size_t maxCount = 1) = 0;
    /**
     * @brief featurePoints 以模板中心点为原点的特征点
     * @param template_id 模板的 ID
     * @return 返回特征点的数组
     */
    std::vector<cv::Point2f> featurePoints(int template_id);
    std::vector<cv::Point2f> featurePoints(const MatchResult &mr);

    cv::Mat modelImage(int radius = 3, cv::Scalar color = cv::Scalar{ 0, 0, 255 }, int thickness = 1);

    void drawFeatures(cv::Mat &img, const MatchResult& results,
                      int radius = 3, cv::Scalar color = cv::Scalar{ 0, 0, 255 }, int thickness = 1 );

    void drawFeaturePoints(cv::Mat &img, const std::vector<cv::Point> pts,
                      int radius = 3, cv::Scalar color = cv::Scalar{ 0, 0, 255 }, int thickness = 1);
    cv::Mat featureImg;
    cv::Mat templateImg;
//    cv::Mat resultImg;
protected:
    /**
     * @brief preprocessModelImage 对模板图像进行预处理。四周增加黑边。
     * @param img
     * @param width_padding
     * @param height_padding
     */
    void preprocessModelImage(const cv::Mat &img,int width_padding = 0, int height_padding = 0);

    /**
     * @brief preprocessTestImage 处理测试图像，要满足图像的长款都是 64 的整倍数。 在四周加黑边。上边、和左边的黑边都是 32 像素。
     * @param img 原始图像
     * @return
     */
    cv::Mat preprocessTestImage(const cv::Mat &img);

    void refine(const std::vector<line2Dup::Match> &matches, size_t maxCount,
                std::vector<MatchResult> &ret);

    cv::RotatedRect rotatedRect(const line2Dup::Match &match);

    void buildFeatureImage(shape_based_matching::shapeInfo_producer::Info &info, int radius = 3,
                           cv::Scalar color = cv::Scalar{ 0, 0, 255 }, int thickness = 1);

    std::vector<cv::Point2f> featurePoints(const line2Dup::Match &match);

    line2Dup::Detector *pDetector;
    std::vector<shape_based_matching::shapeInfo_producer::Info> infos_have_templ; //记录那些能正常生成 template 的 Info
    std::string class_id;
    std::vector<std::string> class_ids;
    int m_width_padding;
    int m_height_padding;
    cv::Mat padded_templateImg;
    cv::Mat padded_mask;
};

}

#endif
